//在测试时要在编译末尾加[-pthread]
#include <stdio.h>
#include <sys/types.h>          
#include <sys/socket.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
//全局数据类型定义
#define ElemType int
#define ElemTypes char
#define Internet_Protocol ("192.168.20.128")
//接收信息
void* recv_msg(void* arg);
ElemType main(){
    //从终端获取连接方端口号
    ElemType port;
    system("clear");
    printf("设置自己端口号: ");
    scanf("%d", &port);
    printf("\n");
    //端口号中0~1024给系统用， 1025~65535给用户用
    if (port <1025 || port > 65535){
        printf("连接端口号范围为1025~65535\n");
        sleep(2);
        system("clear");
        return -1;
    }
    //创建UDP通信通道socket
    ElemType UDP_socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
    if (UDP_socket_fd < 0){
        perror("creat socket fail\n");
        sleep(1);
        system("clear");
        return -1;
    }
    //设置UDP地址并绑定
    struct sockaddr_in local_addr;
    //初始化服务器地址
    bzero(&local_addr, sizeof(local_addr));
    //IPV4协议
    local_addr.sin_family = AF_INET;
    //设置发送方端口号
    local_addr.sin_port = htons(port);
    //系统检测本地网卡， 自动绑定本地IP
    local_addr.sin_addr.s_addr = inet_addr(Internet_Protocol);
    ElemType ret = bind(UDP_socket_fd, (struct sockaddr*)&local_addr, sizeof(local_addr));
    if (ret < 0){
        perror("bind fail");
        close(UDP_socket_fd);
        sleep(1);
        system("clear");
        return -1;
    }
    //开启接收线程
    pthread_t recv_thread;
    pthread_create(&recv_thread, NULL, recv_msg, (void*)&UDP_socket_fd);
    //设置目的IP地址
    struct sockaddr_in dest_addr = {0};
    //IPV4协议
    dest_addr.sin_family = AF_INET;
    //目的端口号
    ElemType dest_port = 0;
    //目的IP地址
    ElemTypes dest_IP[32] = {0};
    //信息缓冲区
    ElemTypes msg[1024] = {0};
    //循环发送信息
    while (1){
        printf("接收方端口号: ");
        scanf("%d",&dest_port);
        printf("\n");
        printf("\n自己端口号: %d\n", port);
        ElemType lobsterarr = dest_port;
        if (0 == lobsterarr){
            //将缓冲区中的杂质装起来
            ElemTypes lobsterarr[1024];
            //进行清空
            scanf("%s", lobsterarr);
            //取消子线程
            pthread_cancel(recv_thread);
            system("clear");
            //退出循环
            printf("退出单聊系统\n");
            sleep(1);
            system("clear");
            break;
        }
        printf("要发信息: ");
        scanf("%s", msg);
        printf("\n");
        if (strcmp(msg, "exit") == 0 || strcmp(msg, "") == 0){
            //取消子线程
            pthread_cancel(recv_thread);
            system("clear");
            //退出循环
            printf("退出单聊系统\n");
            sleep(1);
            system("clear");
            break;
        }
        //设置接收方端口号
        dest_addr.sin_port = htons(dest_port);
        //设置接收方IP
        dest_addr.sin_addr.s_addr = inet_addr(Internet_Protocol);
        sendto(UDP_socket_fd, msg, strlen(msg), 0, (struct sockaddr*)&dest_addr, sizeof(dest_addr));
        //清空缓存
        memset(msg, 0, sizeof(msg));
        memset(dest_IP, 0, sizeof(dest_IP));
    //关闭通信通道
    close(UDP_socket_fd);
    return;
}
}
//接收信息
void* recv_msg(void* arg){
    ElemType ret = 0;
    //通信通道socket
    ElemType* socket_fd = (ElemType*)arg;
    //存储信息发送方的IP地址信息
    struct sockaddr_in src_addr = {0};
    //地址大小
    ElemType len = sizeof(src_addr);
    //信息缓冲区
    ElemTypes msg[1024] = {0};
    //循环接收发来的数据
    while (1){
        ret = recvfrom(*socket_fd, msg, sizeof(msg), 0, (struct sockaddr*)&src_addr, &len);
        if (ret == -1)
            break;
        if (ret != 0){
            system("clear");
            printf("=============\n");
            printf("||来新消息了||\n");
            printf("=============\n");
            sleep(2);
            printf("退出: exit\n");
        }
        //输出信息发送方IP地址与端口号
        printf("\n接收信息: %s\n", msg);
        if (strcmp(msg, "exit") == 0 || strcmp(msg, "") == 0)
            //告知主线程
            break;
        //清空缓存
        memset(msg, 0, sizeof(msg));
    }
    //关闭通信通道socket
    close(*socket_fd);
    return NULL;
}